package doan.chuyennganh.net;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.URI;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;

import android.content.Context;
import doan.chuyennganh.model.ListClassReturnObject;
import doan.chuyennganh.model.ListStudentReturnObject;
import doan.chuyennganh.model.SavedAttendanceDataReturnObject;
import doan.chuyennganh.util.Constants;
import doan.chuyennganh.util.JsonHelper;
import doan.chuyennganh.util.JsonParserHelper;


public class Api extends ApiConnect implements IApi{
	
	private static IApi sMock;
	private static final int CONNECTION_TIMEOUT = 20000;
	private static final int SOCKET_TIMEOUT = 60000;
	
	private String baseUrl= "";

	public Api(Context context) {
		super(context);
	}

	public Api(Context context, String baseUrl) {
		super(context);
		this.baseUrl = baseUrl;
	}

	public static IApi createInstance(Context context, String baseUrl) {
		if (sMock != null) {
			return sMock;
		} else {
			return new Api(context, baseUrl);
		}
	}

	/**
	 * Connect to http via GET method
	 * 
	 * @param url
	 * @param paramList
	 * @return
	 */
	public String excuteGet(String url, List<NameValuePair> paramList) {
		if (null != paramList) {
			url += getStrParam(paramList);
		}
		HttpClient hClient = new DefaultHttpClient();
//		hClient = sslClient(hClient);
		HttpConnectionParams.setConnectionTimeout(hClient.getParams(),
				CONNECTION_TIMEOUT); // Timeout
		HttpConnectionParams.setSoTimeout(hClient.getParams(), SOCKET_TIMEOUT);
		try {
			HttpGet hget = new HttpGet();
			hget.setURI(new URI(url));
			HttpResponse response = hClient.execute(hget);
			StatusLine statusLine = response.getStatusLine();

			if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				response.getEntity().writeTo(out);
				
				String responseString = out.toString();
				out.close();
				return responseString;
			} else {
				return "";
			}
		} catch (ConnectTimeoutException e) {
			e.printStackTrace();
			return "";

		} catch (Exception e) {
			e.printStackTrace();
			return "";

		}
	}

	/**
	 * Post method
	 * 
	 * @param paramList
	 *            : Danh sach va tham so dang NameValuePair
	 * 
	 * @return JSON
	 */
	public String excutePost(String url, List<NameValuePair> paramList) {
		HttpClient httpclient = new DefaultHttpClient();
		httpclient = sslClient(httpclient);
		HttpConnectionParams.setConnectionTimeout(httpclient.getParams(),
				CONNECTION_TIMEOUT); // Timeout
		HttpConnectionParams.setSoTimeout(httpclient.getParams(),
				SOCKET_TIMEOUT);
		HttpPost httppost = new HttpPost(url);

		HttpResponse response = null;
		try {
			httppost.setEntity(new UrlEncodedFormEntity(paramList, "UTF-8"));
			response = httpclient.execute(httppost);
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

			if (HttpStatus.SC_NO_CONTENT == response.getStatusLine()
					.getStatusCode()) {
				return "";
			} else if (HttpStatus.SC_OK == response.getStatusLine()
					.getStatusCode()) {
				response.getEntity().writeTo(byteArrayOutputStream);
				String ret = byteArrayOutputStream.toString();
				return ret;
			} else {
				return "";
			}

		} catch (ConnectTimeoutException e) {
			e.printStackTrace();
			return "";
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
	}
	private HttpClient sslClient(HttpClient client) {
		try {
			X509TrustManager tm = new X509TrustManager() {
				public void checkClientTrusted(X509Certificate[] xcs,
						String string) throws CertificateException {
				}

				public void checkServerTrusted(X509Certificate[] xcs,
						String string) throws CertificateException {
				}

				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}
			};
			SSLContext ctx = SSLContext.getInstance("TLS");
			ctx.init(null, new TrustManager[] { tm }, null);
			SSLSocketFactory ssf = new MySSLSocketFactory(ctx);
			ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
			ClientConnectionManager ccm = client.getConnectionManager();
			SchemeRegistry sr = ccm.getSchemeRegistry();
			sr.register(new Scheme("https", ssf, 443));
			sr.register(new Scheme("http", PlainSocketFactory
					.getSocketFactory(), 80));
			return new DefaultHttpClient(ccm, client.getParams());
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

	public class MySSLSocketFactory extends SSLSocketFactory {
		SSLContext sslContext = SSLContext.getInstance("TLS");

		public MySSLSocketFactory(KeyStore truststore)
				throws NoSuchAlgorithmException, KeyManagementException,
				KeyStoreException, UnrecoverableKeyException {
			super(truststore);

			TrustManager tm = new X509TrustManager() {
				public void checkClientTrusted(X509Certificate[] chain,
						String authType) throws CertificateException {
				}

				public void checkServerTrusted(X509Certificate[] chain,
						String authType) throws CertificateException {
				}

				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}
			};

			sslContext.init(null, new TrustManager[] { tm }, null);
		}

		public MySSLSocketFactory(SSLContext context)
				throws KeyManagementException, NoSuchAlgorithmException,
				KeyStoreException, UnrecoverableKeyException {
			super(null);
			sslContext = context;
		}

		@Override
		public Socket createSocket(Socket socket, String host, int port,
				boolean autoClose) throws IOException, UnknownHostException {
			return sslContext.getSocketFactory().createSocket(socket, host,
					port, autoClose);
		}

		@Override
		public Socket createSocket() throws IOException {
			return sslContext.getSocketFactory().createSocket();
		}
	}
	
	public ListClassReturnObject Login(String username, String password){
			ListClassReturnObject listclass = new ListClassReturnObject();
		try {
			List<NameValuePair> paramList = new ArrayList<NameValuePair>();
			paramList.add(new BasicNameValuePair("user_name", username));
			paramList.add(new BasicNameValuePair("pass_word", password));
			String result = excutePost(baseUrl + Constants.SERVICE_LOGIN, paramList);
			
			listclass = JsonParserHelper.getJsonObjectByMapper(result, ListClassReturnObject.class);
//			JSONArray array = new JSONArray(result);
//			int length = array.length();
//			for (int i = 0; i < length; i++) {
//				JSONObject obj = array.getJSONObject(i);
//				LopHocPhan tmp = new LopHocPhan(obj.getString("malop"), obj.getString("tenmonhoc"));
//				listclass.add(tmp);
//			}
		
		} catch (Exception e) {
			e.printStackTrace();
		
		}
		
		
		return listclass;
		
	}
	
	public ListStudentReturnObject GetListStudent(String malop){
		ListStudentReturnObject list = null;
		try {
			List<NameValuePair> paramList = new ArrayList<NameValuePair>();
			paramList.add(new BasicNameValuePair("ma_lop", malop));
			String result = excutePost(baseUrl + Constants.SERVICE_GET_LIST_STUDENT, paramList);
			
			list = JsonHelper.parseListStudent(result);
			
		} catch (Exception e) {
			e.printStackTrace();
			
		}
		return list;
	}
	public SavedAttendanceDataReturnObject SendingAttendanceData(String data){
		SavedAttendanceDataReturnObject res = new SavedAttendanceDataReturnObject("Sending error!!!", -1);
		try {
			List<NameValuePair> paramList = new ArrayList<NameValuePair>();
			paramList.add(new BasicNameValuePair("diem_danh", data));
			String result = excutePost(baseUrl + Constants.SERVICE_UPDATE_TO_SERVER, paramList);
			
			res = JsonParserHelper.getJsonObjectByMapper(result, SavedAttendanceDataReturnObject.class);
			
		} catch (Exception e) {
			e.printStackTrace();
			
		}
		return res;
	}
}
